package com.ruoyi.project.validation;

import org.springframework.util.Assert;

import javax.annotation.Resource;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import javax.validation.groups.Default;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * 校验器 。 JSR-303以及hibernate校验。 校验约束如： @Null, @NotNull, @Min, @NotBlank等等校验， 也可以扩展自己的约束，如@Mobile
 *
 * @author 挺好的 2023年02月10日 15:00
 */
public abstract class BaseValidator {

    public interface Save extends Default {

    }

    public interface Update extends Default {
        
    }

    /**
     * 校验器
     */
    @Resource (name = "validator")
    protected Validator validator;

    /**
     * 校验单个对象，如果校验失败，抛出ConstraintViolationException
     *
     * @param target
     *         对象
     * @param groups
     *         校验分组
     */
    protected void validation (Object target, Class <?>... groups) {
        Assert.notNull(target, "validation target must not null");

        Set <ConstraintViolation <Object>> constraintViolations = this.validator.validate(target, groups);

        if (constraintViolations.isEmpty()) {
            return;
        }

        Iterator <ConstraintViolation <Object>> it = constraintViolations.iterator();

        if (it.hasNext()) {
            ConstraintViolation <Object> constraintViolation = it.next();
            // 获取消息
            String message = constraintViolation.getMessage();

            throw new ConstraintViolationException(message);
        }
    }

    /**
     * 校验多个对象，如果校验失败，抛出ConstraintViolationException
     *
     * @param targets
     *         对象集合
     * @param groups
     *         校验分组
     */
    protected void validation (Collection <Object> targets, Class <?>... groups) {
        Assert.notEmpty(targets, "validation targets is not empty");

        for (Object target : targets) {
            this.validation(target, groups);
        }
    }

    /**
     * 校验对象的某个属性
     *
     * @param type
     *         对象类型
     * @param property
     *         属性名称
     * @param value
     *         值
     * @param groups
     *         校验分组
     */
    protected void validation (Class <?> type, String property, Object value, Class <?>... groups) {
        Assert.notNull(type, "validation class type is not null");
        Assert.hasText(property, "validation property is not empty");

        Set <?> constraintViolations = this.validator.validateValue(type, property, value, groups);
        if (constraintViolations.isEmpty()) {
            return;
        }

        Iterator <ConstraintViolation <?>> it = (Iterator <ConstraintViolation <?>>) constraintViolations.iterator();

        if (it.hasNext()) {
            ConstraintViolation <?> constraintViolation = it.next();
            // 获取消息
            String message = constraintViolation.getMessage();

            throw new ConstraintViolationException(message);
        }

    }

    /**
     * 校验对象的校验对象的多个属性，多个属性以map封装
     *
     * @param type
     *         对象类型
     * @param properties
     *         属性和值的map对象
     * @param groups
     *         校验分组
     */
    protected void validation (Class <?> type, Map <String, Object> properties, Class <?>... groups) {
        Assert.notNull(type, "validation class type is not null");
        Assert.notEmpty(properties, "properties map is not empty");

        for (Map.Entry <String, Object> entry : properties.entrySet()) {
            this.validation(type, entry.getKey(), entry.getValue(), groups);
        }
    }

}
